package com.hope.minio.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hope.minio.common.result.Result;
import com.hope.minio.config.MinioConfig;
import com.hope.minio.mapper.FileChunkMapper;
import com.hope.minio.model.FileChunk;
import com.hope.minio.service.FileUploadService;
import com.hope.minio.service.MinioService;
import com.hope.minio.utils.MinioUtil;
import io.minio.PutObjectOptions;
import io.minio.messages.CompleteMultipartUpload;
import io.minio.messages.Part;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 功能描述: FileUploadServiceImpl
 *
 * @return:
 * @Author: zhangTao
 * @Date: 2020/8/28 1:59
 */
@Service
public class FileUploadServiceImpl implements FileUploadService {

    @Autowired
    private FileChunkMapper fileChunkMapper;

    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private MinioConfig minioConfig;

    @Value("${minio.bucketName}")
    private String bucketName;

    private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;

    @Override
    public Result<FileChunk> getSuccessChunks(String md5) {
        LambdaQueryWrapper<FileChunk> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FileChunk::getMd5, md5);
        FileChunk fileChunk = fileChunkMapper.selectOne(queryWrapper);
        if (fileChunk == null) {
            return new Result(000, "md5无效");
        }
        return new Result(200, "成功", fileChunk);
    }

    @Override
    public Result<FileChunk> newMultipart(FileChunk fileChunk) {
        Long totalChunks = fileChunk.getTotalChunks();
        if (totalChunks < 0) {
            return new Result(000, "totalChunkCounts is illegal.");
        }
        if (totalChunks > PutObjectOptions.MAX_MULTIPART_COUNT || totalChunks <= 0) {
            return new Result(000, "totalChunkCounts is illegal.");
        }
        if (fileChunk.getSize() > PutObjectOptions.MAX_PART_SIZE || fileChunk.getSize() <= 0) {
            return new Result(000, "size is illegal.");
        }
        String uuid = IdUtil.fastSimpleUUID();
        String fileName = fileChunk.getFileName();
        String uploadId = DateUtil.date().toString("yyyy/MM/dd/") + IdUtil.fastSimpleUUID() + fileName.substring(fileName.lastIndexOf("."));
        fileChunk.setUploadId(uploadId);
        int insert = fileChunkMapper.insert(fileChunk);

        return new Result<>(200, "成功", fileChunk);
    }

    @Override
    public Result<String> getMultipartUrl(FileChunk fileChunk) {
//        uuid: file.uuid,
//                uploadID: file.uploadID,
//                size: partSize,
//                chunkNumber: currentChunk+1
        if (fileChunk.getChunkNumber() == null || fileChunk.getChunkNumber() < 0) {
            return new Result(000, "totalChunkCounts is illegal.");
        }
        if (fileChunk.getSize() == null || fileChunk.getSize() < 0 || fileChunk.getSize() > PutObjectOptions.MAX_OBJECT_SIZE) {
            return new Result(000, "size is illegal.");
        }
        String returnUrlStr = minioUtil.presignedPutObject(bucketName, fileChunk.getUploadId(), DEFAULT_EXPIRY_TIME);
        String returnUrl = returnUrlStr.replaceAll(minioConfig.getEndpoint() + ":" + minioConfig.getPort(), "minio");
        return new Result(200, "成功", returnUrl);
    }

    @Override
    public Result<String> completeMultipart(FileChunk dto) {
        LambdaQueryWrapper<FileChunk> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FileChunk::getUuid, dto.getUuid());
        FileChunk fileChunk = fileChunkMapper.selectOne(queryWrapper);
        if (fileChunk == null) {
            return new Result<>(000, "失败");
        }
        completeMultiPartUpload(fileChunk.getUuid(), fileChunk.getUploadId(), fileChunk.getCompletedParts());
        return new Result<>();
    }

    public Result completeMultiPartUpload(String uuid, String uploadID, String complParts) {
        String[] splitList = complParts.split(",");
        List<Part> parts = new ArrayList<>(splitList.length);
        for (String compart : splitList) {
            if (StrUtil.isEmpty(compart)) {
                return new Result(000, "失败");
            }
            String partNumber = compart.split("-")[0];
            String eTag = compart.split("-")[1];
            Part part = new Part(Integer.parseInt(partNumber), eTag);
            parts.add(part);
        }
        Part [] partArr = (Part []) parts.toArray(new Part[parts.size()]);

         CompleteMultipartUpload completeMultipartUpload = new CompleteMultipartUpload(partArr);
        return null;
    }
}
